package com.afollestad.commons.folderselector;

import com.afollestad.commons.ResourceTable;
import com.afollestad.materialdialogs.internal.MDButton;
import com.afollestad.materialdialogs.internal.MDRootLayout;
import com.afollestad.materialdialogs.internal.ThemeSingleton;
import com.afollestad.materialdialogs.utils.ResUtil;
import ohos.agp.components.*;
import ohos.agp.utils.Color;
import ohos.agp.window.dialog.CommonDialog;
import ohos.app.Context;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

public class FileChooserDialog extends CommonDialog {

    private static final String DEFAULT_TAG = "[MD_FILE_SELECTOR]";

    private Context mContext;
    private File parentFolder;
    private File[] parentContents;
    private boolean canGoUp = true;
    private FileCallback callback;
    private MDRootLayout mDialogLayout;
    private MainListProvider itemProvider;

    public FileChooserDialog(Context context) {
        super(context);
        mContext = context;
        parentFolder = new File(getBuilder().initialPath);
        checkIfCanGoUp();
        parentContents = listFiles(getBuilder().mimeType, getBuilder().extensions);
        initDialogLayout();
        setLayoutDimensions();
    }

    private void setLayoutDimensions() {
        mDialogLayout.setLayoutMeasureDimensions((width, height, lcHeight) -> {
            mDialogLayout.setLayoutConfig(new MDRootLayout.LayoutConfig(width, height));
            setSize(width, height);
        });
    }

    private void initDialogLayout() {
        mDialogLayout = (MDRootLayout) LayoutScatter.getInstance(mContext).parse(ResourceTable.Layout_md_dialog_filechooser, null, false);
        if (!(mDialogLayout instanceof ComponentContainer)) {
            return;
        }
        try {
            ((Text) mDialogLayout.findComponentById(ResourceTable.Id_md_title)).setText(parentFolder.getCanonicalPath());
        } catch (IOException e) {
            e.printStackTrace();
        }
        ListContainer listContainer = (ListContainer) mDialogLayout.findComponentById(ResourceTable.Id_listC);
        itemProvider = new MainListProvider(mContext, getContentsArray());
        listContainer.setItemProvider(itemProvider);
        listContainer.setItemClickedListener((listContainer1, component, i, l) -> onSelection(i));
        MDButton posButton = (MDButton) mDialogLayout.findComponentById(ResourceTable.Id_md_buttonDefaultPositive);
        MDButton negButton = (MDButton) mDialogLayout.findComponentById(ResourceTable.Id_md_buttonDefaultNegative);
        MDButton neuButton = (MDButton) mDialogLayout.findComponentById(ResourceTable.Id_md_buttonDefaultNeutral);
        negButton.setText(getBuilder().cancelButton);
        posButton.setVisibility(Component.HIDE);
        neuButton.setVisibility(Component.HIDE);
        negButton.setClickedListener((c) -> hide());

        int widgetColor = (ThemeSingleton.get().widgetColor == 0) ? ResUtil.getColor(mContext, ResourceTable.Color_colorAccent) : ThemeSingleton.get().widgetColor;

        Color color = new Color(widgetColor);
        posButton.setTextColor(color);
        negButton.setTextColor(color);
        negButton.setTextColor(color);

        setContentCustomComponent(mDialogLayout);
    }

    private CharSequence[] getContentsArray() {
        if (parentContents == null) {
            if (canGoUp) {
                return new String[]{getBuilder().goUpLabel};
            }
            return new String[]{};
        }
        String[] results = new String[parentContents.length + (canGoUp ? 1 : 0)];
        if (canGoUp) {
            results[0] = getBuilder().goUpLabel;
        }
        for (int i = 0; i < parentContents.length; i++) {
            results[canGoUp ? i + 1 : i] = parentContents[i].getName();
        }
        return results;
    }

    private File[] listFiles(String mimeType, String[] extensions) {
        File[] contents = parentFolder.listFiles();
        List<File> results = new ArrayList<>();
        if (contents != null) {
            for (File fi : contents) {
                if (fi.isDirectory()) {
                    results.add(fi);
                } else {
                    if (extensions != null) {
                        boolean found = false;
                        for (String ext : extensions) {
                            if (fi.getName().toLowerCase().endsWith(ext.toLowerCase())) {
                                found = true;
                                break;
                            }
                        }
                        if (found) {
                            results.add(fi);
                        }
                    } else if (mimeType != null) {
                        results.add(fi);
                    }
                }
            }
            results.sort(new FileSorter());
            return results.toArray(new File[0]);
        }
        return null;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (callback != null) {
            callback.onFileChooserDismissed(this);
        }
    }

    private void onSelection(int i) {
        if (canGoUp && i == 0) {
            parentFolder = parentFolder.getParentFile();
            if (parentFolder.getAbsolutePath().equals("/storage/emulated")) {
                parentFolder = parentFolder.getParentFile();
            }
            canGoUp = parentFolder.getParent() != null;
        } else {
            parentFolder = parentContents[canGoUp ? i - 1 : i];
            canGoUp = true;
        }
        if (parentFolder.isFile()) {
            callback.onFileSelection(this, parentFolder);
            hide();
        } else {
            parentContents = listFiles(getBuilder().mimeType, getBuilder().extensions);
            try {
                ((Text) mDialogLayout.findComponentById(ResourceTable.Id_md_title)).setText(parentFolder.getCanonicalPath());
            } catch (IOException e) {
                e.printStackTrace();
            }
            itemProvider.setUpdatedItems(getContentsArray());
        }
    }

    private void checkIfCanGoUp() {
        try {
            canGoUp = parentFolder.getPath().split("/").length > 1;
        } catch (IndexOutOfBoundsException e) {
            canGoUp = false;
        }
    }

    @Override
    protected void onCreate() {
        super.onCreate();
        if (mContext instanceof FileCallback) {
            callback = (FileCallback) mContext;
        } else {
            throw new IllegalStateException(
                    "FileChooserDialog needs to be shown from an Activity/Fragment implementing FileCallback.");
        }
    }

    private Builder getBuilder() {
        return Builder.getBuilder();
    }

    public interface FileCallback {

        void onFileSelection(FileChooserDialog dialog, File file);

        void onFileChooserDismissed(FileChooserDialog dialog);
    }

    public static class Builder implements Serializable {
        static Builder mBuilder;
        final transient Context context;
        int cancelButton;
        String initialPath;
        String mimeType;
        String[] extensions;
        String tag;
        String goUpLabel;
        String mediumFont;
        String regularFont;

        public Builder(Context context) {
            this.context = context;
            cancelButton = ResourceTable.String_md_cancel_label;
            initialPath = "/storage/emulated/0";
            mimeType = "";//null;
            goUpLabel = "...";
            if (mBuilder == null) {
                mBuilder = this;
            }
        }

        static Builder getBuilder() {
            return mBuilder;
        }

        public Builder typeface(String medium, String regular) {
            this.mediumFont = medium;
            this.regularFont = regular;
            return this;
        }

        public Builder cancelButton(int text) {
            cancelButton = text;
            return this;
        }

        public Builder initialPath(String initialPath) {
            if (initialPath == null) {
                initialPath = File.separator;
            }
            this.initialPath = initialPath;
            return this;
        }

        public Builder mimeType(String type) {
            mimeType = type;
            return this;
        }

        public Builder extensionsFilter(String... extensions) {
            this.extensions = extensions;
            return this;
        }

        public Builder tag(String tag) {
            if (tag == null) {
                tag = DEFAULT_TAG;
            }
            this.tag = tag;
            return this;
        }

        public Builder goUpLabel(String text) {
            goUpLabel = text;
            return this;
        }

        FileChooserDialog build() {
            return new FileChooserDialog(context);
        }

        public void show() {
            FileChooserDialog dialog = build();
            dialog.show();
        }
    }

    private static class FileSorter implements Comparator<File> {

        @Override
        public int compare(File lhs, File rhs) {
            if (lhs.isDirectory() && !rhs.isDirectory()) {
                return -1;
            } else if (!lhs.isDirectory() && rhs.isDirectory()) {
                return 1;
            } else {
                return lhs.getName().compareTo(rhs.getName());
            }
        }
    }

}
